package com.mofeng.myshop.service.user.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mofeng.myshop.domain.dto.SendEmailDto;
import com.mofeng.myshop.domain.dto.user.UserDto;
import com.mofeng.myshop.domain.po.*;
import com.mofeng.myshop.domain.po.base.BaseEntity;
import com.mofeng.myshop.domain.vo.base.PageMp;
import com.mofeng.myshop.domain.dto.search.UserSearchDto;
import com.mofeng.myshop.domain.vo.user.UserVo;
import com.mofeng.myshop.mapper.*;
import com.mofeng.myshop.service.IOrderFromService;
import com.mofeng.myshop.service.PermissionService;
import com.mofeng.myshop.service.user.UserService;
import com.mofeng.myshop.service.user.UserUtilsService;
import com.mofeng.myshop.until.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.util.TextUtils;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {

    private final UserBaseMapper userMapper;

    private final UserInfoMapper userInfoMapper;

    private final UserPowerMapper userPowerMapper;

    private final SettingMapper settingsMapper;

    private final BCryptPasswordEncoder bcryptPasswordEncoder;

    private final PermissionService permissionService;

    private final UserUtilsService userUtilsService;

    private final UserRoleMapper userRoleMapper;

    private final IOrderFromService orderFromService;


    /**
     * 生成用户详细信息类
     */
    private UserInfo getUserDetailInfo(Long userId) {
        UserInfo userInfo = new UserInfo();
        userInfo.setId(userId);
        userInfo.setSex("0");
        userInfo.setIntroduction(Constants.User.DEFAULT_SIGN);
        userInfo.setAddress("");
        userInfo.setMoney(Constants.User.DEFAULT_MONEY);
        userInfo.setAmount(Constants.User.DEFAULT_MONEY);
        userInfo.setInvitationCode(UUID.randomUUID().toString().replace("-", ""));
        return userInfo;
    }

    /**
     * 获取权限对象
     */
    private UserPower getUserPower(String name, int power) {
        UserPower userPowerUser = new UserPower();
        userPowerUser.setNumber(power);
        userPowerUser.setName(name);
        return userPowerUser;
    }

    /**
     * 初始化网站设置
     */
    private List<Setting> initSetting() {
        List<Setting> settingList = new ArrayList<>();

        Setting webTitle = new Setting();
        webTitle.setName("网站名称");
        webTitle.setKey(Constants.Settings.WEB_TITLE);
        webTitle.setValue(Constants.Settings.DEFAULT_TITLE);
        settingList.add(webTitle);

        Setting webDescription = new Setting();
        webDescription.setName("网站描述");
        webDescription.setKey(Constants.Settings.WEB_DESCRIPTION);
        webDescription.setValue("");
        settingList.add(webDescription);

        Setting webKeywords = new Setting();
        webKeywords.setName("网站关键字");
        webKeywords.setKey(Constants.Settings.WEB_KEYWORDS);
        webKeywords.setValue("");
        settingList.add(webKeywords);

        Setting webLogo = new Setting();
        webLogo.setName("网站logo");
        webKeywords.setKey(Constants.Settings.WEB_LOGO);
        webKeywords.setValue("");
        settingList.add(webLogo);

        int i = 1;
        for (Setting setting : settingList) {
            setting.setOrderIndex(i++);
        }
        return settingList;
    }


    /**
     * 初始化管理员账号（网站信息初始化）
     *
     * @param userDto 管理员信息
     */
    @Transactional
    @Override
    public R initAdminAccount(UserDto userDto) {
        //检查是否初始化
        UserBase user = userDto.toEntity();
        Setting managerAccountInitState = settingsMapper.findByKey(Constants.Settings.MANAGER_ACCOUNT_INIT_STATE);
        if (managerAccountInitState != null) {
            return R.FAILED("管理员帐号已经初始化");
        }
        if (TextUtils.isEmpty(user.getPassword())) {
            return R.FAILED("密码不能为空");
        }
        if (TextUtils.isEmpty(user.getEmail())) {
            return R.FAILED("邮箱不能为空");
        }
        //补充数据
        user.setImage(Constants.User.DEFAULT_AVATAR);
        user.setState(Constants.State.DEFAULT_STATE);
        /*密码加密*/
        String password = MyUtil.MD5Util.calculateMD5(user.getPassword());//获取密码
        user.setPassword(bcryptPasswordEncoder.encode(password));//设置加密密吗
        //更新已经添加的标记
        //肯定没有的（管理员账户）
        Setting setting = new Setting();
        setting.setKey(Constants.Settings.MANAGER_ACCOUNT_INIT_STATE);
        setting.setValue("1");
        setting.setOrderIndex(0);
        //用户信息补充
        UserInfo userInfo = getUserDetailInfo(user.getId());
        //角色权限补充
        UserPower userPowerRoot = getUserPower(Constants.User.ROLE_ROOT_NAME, Constants.User.ROLE_ROOT);
        userPowerMapper.insert(userPowerRoot);

        user.setPowerId(userPowerRoot.getId());
        userMapper.insert(user);
        /*其他四种种默认权限的补充*/
        //管理员
        UserPower userPowerMaster = getUserPower(Constants.User.ROLE_MASTER_NAME, Constants.User.ROLE_MASTER);
        //管理员
        UserPower userPowerAdmin = getUserPower(Constants.User.ROLE_ADMIN_NAME, Constants.User.ROLE_ADMIN);
        //普通用户
        UserPower userPowerNormal = getUserPower(Constants.User.ROLE_NORMAL_NAME, Constants.User.ROLE_NORMAL);
        //匿名用户
        UserPower userPowerUser = getUserPower(Constants.User.ROLE_USER_NAME, Constants.User.ROLE_USER);

        //网站基础信息的初始化
        List<Setting> settings = initSetting();

        //保存到数据库里
        userPowerMapper.insert(userPowerMaster);
        userPowerMapper.insert(userPowerAdmin);
        userPowerMapper.insert(userPowerNormal);
        userPowerMapper.insert(userPowerUser);
        userInfoMapper.insert(userInfo);
        settingsMapper.insert(setting);
        for (Setting settingItem : settings) {
            settingsMapper.insert(settingItem);
        }
        return R.SUCCESS("初始化成功!");
    }

    /**
     * 用户注册：仅限于普通用户注册
     *
     * @param userDto   用户封装类
     * @param emailCode 邮箱验证码
     */
    @Override
    @Transactional
    public R register(UserDto userDto, String emailCode) {
        //检查当前用户名是否已经注册。
        UserBase user = userDto.toEntity();
        String userName = user.getName();
        String password = user.getPassword();
        String email = user.getEmail();
        if (MyUtil.StringUtil.isEmpty(userName)) {
            return R.FAILED("用户名不能为空！");
        }
        if (MyUtil.StringUtil.isEmpty(password)) {
            return R.FAILED("密码不能为空！");
        }
        if (userUtilsService.checkUserName(userName)) {
            return R.FAILED("此用户名已存在");
        }
        //检查邮箱格式是否正确。
        if (MyUtil.StringUtil.isEmpty(email)) {
            return R.FAILED("邮箱不能为空！");
        }
        if (!MyUtil.RegularUtil.isEmailAddresOk(email)) {
            return R.FAILED("邮箱格式不正确！");
        }
        //检查该邮箱是否已经注册。
        if (userUtilsService.checkEmail(email)) {
            return R.FAILED("邮箱已注册！");
        }
        //检查邮箱验证码是否正确。
        String redisEmailCode = userUtilsService.getAndCheckEmailCode(email, emailCode);
        //达到可以注册的条件。
        //对密码进行加密。
        user.setPassword(bcryptPasswordEncoder.encode(password));
        //补全数据。 包括:注册IP,登录IP,角色,头像,创建时间,更新时间。
        user.setState(Constants.State.DEFAULT_STATE);
        user.setImage(Constants.User.DEFAULT_AVATAR);
        //保存到数据库中。
        userMapper.insert(user);
        //用户的详细信息
        UserInfo userInfo = getUserDetailInfo(user.getId());
        userInfoMapper.insert(userInfo);
        //用户的权限
        UserPower userPower = userPowerMapper.findPowerByName(Constants.User.ROLE_USER_NAME);
        user.setPowerId(userPower.getId());
        userMapper.updateById(user);
        // 删除用户验证信息
        userUtilsService.removeValidateMsg(email);
        //第九步:返回结果。
        return R.SUCCESS("注册成功");
    }

    /**
     * 登录
     *
     * @param userDto 用户封装类
     */
    @Override
    @Transactional
    public R login(UserDto userDto) {
        //检查是否是人为操作，是否验证了图灵码
        userUtilsService.checkCaptchaState();
        UserBase user = userDto.toEntity();
        String userName = user.getName();
        String password = user.getPassword();
        if (MyUtil.StringUtil.isEmpty(userName)) {
            return R.FAILED("用户名不能为空！");
        }
        if (MyUtil.StringUtil.isEmpty(password)) {
            return R.FAILED("密码不能为空！");
        }
        UserBase userByDb = userMapper.loginFindByUserName(userName);
        userUtilsService.checkLoginCount(userByDb == null ? null : userByDb.getName());//检查登录状态
        if (userByDb == null || (Constants.State.DELETE_STATE.equals(userByDb.getState()))) {
            throw new RuntimeException("用户名或密码错误");
        }
        //对比用户名密码是否正确
        boolean matches = bcryptPasswordEncoder.matches(password, userByDb.getPassword());
        if (!matches) {
            throw new RuntimeException("用户名或密码错误");
        }
        //正确
        // 判断用户状态
        if (Constants.State.OTHER_STATE.equals(userByDb.getState())) {
            return R.FAILED("当前用户状态异常，请联系管理员查看");
        }
        String from = userDto.getFrom();
        userUtilsService.createToken(userByDb, from);
        //修改用户登录IP、登录时间
        userByDb.setUpdateTime(new Date());

        int i = userMapper.updateById(userByDb);
        if (i == 0) {
            return R.FAILED("登陆失败，请稍后重试。");
        }
        userByDb.setPassword(null);
        userByDb.setEmail(null);
        userByDb.setPhone(null);
        userByDb.setState(null);
        return R.SUCCESS(" “" + userByDb.getName() + "” 欢迎回来", new UserVo(userByDb));
    }

    /**
     * 获取登录用户信息
     */
    @Override
    public R getLoginUser() {
        UserVo userByToken = userUtilsService.parseToken();
        if (userByToken == null) {
            return R.FAILED("用户未登录");
        }
        UserBase userBase = userMapper.findAllInfoById(Long.parseLong(userByToken.getId()));
        if (userBase != null) {
            userByToken = new UserVo(userBase);
        }
        return R.SUCCESS("查询成功").setData(userByToken);
    }

    /**
     * 获取用户信息
     *
     * @param userId 用户ID
     */
    @Override
    public R getUserInfo(String userId) {
        if (MyUtil.StringUtil.isEmpty(userId)) {
            throw new RuntimeException("用户ID不能为空");
        }
        UserBase userByDb = userMapper.findAllInfoById(MyUtil.NumberUtil.asLong(userId));
        if (userByDb == null || Constants.State.DELETE_STATE.equals(userByDb.getState())) {
            return R.FAILED("查询失败！没有此用户");
        }
        return R.SUCCESS("查询成功！").setData(new UserVo(userByDb));
    }

    /**
     * 删除用户 root权限
     *
     * @param userIdList 用户的ID
     */
    @Override
    @Transactional
    public R deleteUser(List<String> userIdList) {
        List<UserBase> UserInfoBase = userMapper.findAllById(userIdList);

        List<UserBase> delUserbase = new ArrayList<>();
        List<UserBase> updateUserbase = new ArrayList<>();

        boolean root = permissionService.ROOT();
        for (UserBase userBase : UserInfoBase) {
            String state = userBase.getState();
            if ((Constants.State.DELETE_STATE.equals(state) || Constants.State.OTHER_STATE.equals(state)) && root) {
                delUserbase.add(userBase);
            }
            if (Constants.State.DEFAULT_STATE.equals(state)) {
                userBase.setState(Constants.State.DELETE_STATE);
                updateUserbase.add(userBase);
            }
        }

        //todo 修改
        for (UserBase userBase : updateUserbase) {
            userMapper.updateById(userBase);
        }

        if (!delUserbase.isEmpty()) {
            List<Long> delIdList = delUserbase.stream().map(BaseEntity::getId).toList();
            userMapper.deleteBatchIds(delIdList);
            userInfoMapper.deleteBatchIds(delIdList);
        }

        for (UserBase userBase : delUserbase) {
            userUtilsService.deleteOldToken(new UserVo(userBase), true);
        }
        return R.SUCCESS("删除成功！");
    }

    /**
     * 查询用户列表 管理员以上权限
     *
     * @param userSearchVo 用户的搜索信息
     */
    @Override
    public R userListAdmin(UserSearchDto userSearchVo) {
        Page<UserBase> userBasePage = userSearchVo.getPageMp();

        String key = userSearchVo.getKeyword();

        String roles = userSearchVo.getRoleId();

        String powerId = userSearchVo.getPowerId();

        String moneyMinStr = userSearchVo.getMoneyMin();
        Long moneyMin = null;
        if (!MyUtil.StringUtil.isEmpty(moneyMinStr)) {
            moneyMin = MyUtil.NumberUtil.asLong(moneyMinStr);
        }
        String moneyMaxStr = userSearchVo.getMoneyMax();
        Long moneyMax = null;
        if (!MyUtil.StringUtil.isEmpty(moneyMaxStr)) {
            moneyMax = MyUtil.NumberUtil.asLong(moneyMaxStr);
        }
        String amountMinStr = userSearchVo.getAmountMin();
        Long amountMin = null;
        if (!MyUtil.StringUtil.isEmpty(amountMinStr)) {
            amountMin = MyUtil.NumberUtil.asLong(amountMinStr);
        }
        String amountMaxStr = userSearchVo.getAmountMax();
        Long amountMax = null;
        if (!MyUtil.StringUtil.isEmpty(amountMaxStr)) {
            amountMax = MyUtil.NumberUtil.asLong(amountMaxStr);
        }

        if (permissionService.ROOT()) {
            userBasePage = userMapper.findList(key, roles, powerId, moneyMin, moneyMax, amountMin, amountMax, null, userBasePage);
//            userBasePage = userMapper.findList(userName, email, roles, gameName, null, userBasePage);
        } else {
//            userBasePage = userMapper.findList(userName, email, roles, gameName, Constants.State.DEFAULT_STATE, userBasePage);
            userBasePage = userMapper.findList(key, roles, powerId, moneyMin, moneyMax, amountMin, amountMax, Constants.State.DEFAULT_STATE, userBasePage);
        }
        List<UserBase> userBaseList = userBasePage.getRecords();
        for (UserBase userBase : userBaseList) {
            userBase.setPassword(null);
        }
//        List<UserInfo> userInfoList = userInfoMapper.finAll();
//        List<UserPower> userPowerList = userPowerMapper.finAll();
//        List<UserRole> userRoleList = userRoleMapper.findAll();
//        assembleUserMsg(userBaseList, userInfoList, userPowerList, userRoleList);
        return R.SUCCESS("查询成功！").setData(new PageMp<>(userBasePage, UserVo::new));
    }

    /**
     * 查询用户列表 前端显示
     *
     * @param userSearchVo 用户的搜索信息
     */
    @Override
    public R userListPortal(UserSearchDto userSearchVo) {

        Page<UserBase> userBasePage = userSearchVo.getPageMp();
        String key = userSearchVo.getKeyword();

        String roles = userSearchVo.getRoleId();

        String powerId = userSearchVo.getPowerId();

        String moneyMinStr = userSearchVo.getMoneyMin();
        Long moneyMin = null;
        if (!MyUtil.StringUtil.isEmpty(moneyMinStr)) {
            moneyMin = MyUtil.NumberUtil.asLong(moneyMinStr);
        }
        String moneyMaxStr = userSearchVo.getMoneyMax();
        Long moneyMax = null;
        if (!MyUtil.StringUtil.isEmpty(moneyMaxStr)) {
            moneyMax = MyUtil.NumberUtil.asLong(moneyMaxStr);
        }
        String amountMinStr = userSearchVo.getAmountMin();
        Long amountMin = null;
        if (!MyUtil.StringUtil.isEmpty(amountMinStr)) {
            amountMin = MyUtil.NumberUtil.asLong(amountMinStr);
        }
        String amountMaxStr = userSearchVo.getAmountMax();
        Long amountMax = null;
        if (!MyUtil.StringUtil.isEmpty(amountMaxStr)) {
            amountMax = MyUtil.NumberUtil.asLong(amountMaxStr);
        }
        userBasePage = userMapper.findList(key, roles, powerId, moneyMin, moneyMax, amountMin, amountMax, Constants.State.DEFAULT_STATE, userBasePage);
        List<UserBase> userBaseList = userBasePage.getRecords();
        for (UserBase userBase : userBaseList) {
            userBase.setPassword(null);
            userBase.setPower(null);
        }
        return R.SUCCESS("查询成功！").setData(new PageMp<>(userBasePage, UserVo::new));
    }

    /**
     * 组装用户信息
     *
     * @param userBaseList  用户基本信息
     * @param userInfoList  用户其他信息
     * @param userPowerList 用户权限信息
     * @param userRoleList  用户会员信息
     */
    private void assembleUserMsg(List<UserBase> userBaseList, List<UserInfo> userInfoList, List<UserPower> userPowerList, List<UserRole> userRoleList) {
        Map<Long, List<UserInfo>> userInfoMap = new HashMap<>();
        if (userInfoList != null) {
            userInfoMap = userInfoList.stream().collect(Collectors.groupingBy(UserInfo::getId));
        }
        Map<Long, List<UserPower>> userPowerMap = new HashMap<>();
        if (userPowerList != null) {
            userPowerMap = userPowerList.stream().collect(Collectors.groupingBy(BaseEntity::getId));
        }
        Map<Long, List<UserRole>> userRoleMap = new HashMap<>();
        if (userRoleList != null) {
            userRoleMap = userRoleList.stream().collect(Collectors.groupingBy(BaseEntity::getId));
        }

        for (UserBase userBase : userBaseList) {
            Long powerId = userBase.getPowerId();
            Long roleId = userBase.getRoleId();
            Long id = userBase.getId();

            List<UserInfo> userInfoListItem = userInfoMap.get(id);
            if (userInfoListItem != null) {
                userBase.setInfo(userInfoListItem.get(0));
            }
            List<UserPower> userPowerListItem = userPowerMap.get(powerId);
            if (userPowerListItem != null) {
                userBase.setPower(userPowerListItem.get(0));
            }
            List<UserRole> userRoleListItem = userRoleMap.get(roleId);
            if (userRoleListItem != null) {
                userBase.setRole(userRoleListItem.get(0));
            }
        }
    }

    /**
     * 修改用户信息 自己
     *
     * @param userDto 用户修改的信息
     */
    @Transactional
    @Override
    public R updateUserInfo(UserDto userDto) {
        UserBase userFromDB = userMapper.findById(MyUtil.NumberUtil.asLong(userDto.getId()));
        if (!permissionService.ownOrRoot(userDto.getId())) {
            return R.FAILED("您无权修改此用户信息");
        }
        if (userFromDB == null) {
            return R.FAILED("找不到用户信息，请检查重试~");
        }
        String userName = userDto.getName();
        if (!TextUtils.isEmpty(userName)) {
            if (!userFromDB.getName().equals(userName)) {
                if (userUtilsService.checkUserName(userName)) {
                    return R.FAILED("用户名已经存在!");
                }
            }
            userFromDB.setName(userName);
            userUtilsService.deleteOldToken(new UserVo(userFromDB), true);
        }
        String email = userDto.getEmail();
        if (TextUtils.isEmpty(email) && !userFromDB.getEmail().equals(email)) {
            if (userUtilsService.checkEmail(email)) {
                return R.FAILED("邮箱已经存在!");
            }
            userFromDB.setEmail(email);
            userUtilsService.deleteOldToken(new UserVo(userFromDB), true);
        }
        String phone = userDto.getPhone();
        if (TextUtils.isEmpty(phone) && !userFromDB.getPhone().equals(phone)) {
            if (userUtilsService.checkPhone(phone)) {
                return R.FAILED("手机已经存在!");
            }
            userFromDB.setPhone(phone);
            userUtilsService.deleteOldToken(new UserVo(userFromDB), true);
        }
        UserBase user = userDto.toEntity();
        UserInfo userInfo = user.getInfo();
        userMapper.updateById(userFromDB);
        userInfoMapper.updateById(userInfo);
        return R.SUCCESS("修改成功！");
    }

    /**
     * root用户 修改用户信息 需要root权限
     */
    @Override
    @Transactional
    public R adminUpdateUserInfo(UserDto userDto) {
        UserBase entity = userDto.toEntity();
        userMapper.updateById(entity);
        return R.SUCCESS("修改成功！");
    }


    /**
     * 修改密码（用户）邮箱
     *
     * @param email       邮箱
     * @param newPassword 新密码
     * @param emailCode   邮箱验证码
     */
    @Override
    @Transactional
    public R updatePassword(String email, String newPassword, String emailCode) {
        if (TextUtils.isEmpty(email)) {
            return R.FAILED("邮箱未填写。");
        }
        UserBase userFromDB = userMapper.findByEmail(email);
        if (userFromDB == null) {
            return R.FAILED("邮箱验证失败");
        }
        String code = userUtilsService.getAndCheckEmailCode(email, emailCode);
        if (bcryptPasswordEncoder.matches(newPassword, userFromDB.getPassword())) {
            return R.FAILED("新密码不能与旧密码一样");
        }
        userFromDB.setPassword(bcryptPasswordEncoder.encode(newPassword));

        userMapper.updateById(userFromDB);
        // 删除用户验证信息
        userUtilsService.removeValidateMsg(email);
        //删除旧的Token,需要重新登陆
        userUtilsService.deleteOldToken(new UserVo(userFromDB), true);
        return R.SUCCESS("修改成功！");
    }

    /**
     * Root重置用用户密码
     *
     * @param userId   用户ID
     * @param password 密码
     */
    @Override
    @Transactional
    public R resetPassword(String userId, String password) {
        UserBase userFromDB = userMapper.findById(MyUtil.NumberUtil.asLong(userId));
        if (userFromDB == null) {
            return R.FAILED("没有此用户");
        }
        if (bcryptPasswordEncoder.matches(password, userFromDB.getPassword())) {
            return R.FAILED("新密码不能与旧密码一样");
        }
        userFromDB.setPassword(bcryptPasswordEncoder.encode(password));
        int i = userMapper.updateById(userFromDB);
        if (i == 0) {
            return R.FAILED("密码重置失败，请检查后重试");
        }
        userUtilsService.deleteOldToken(new UserVo(userFromDB), true);
        return R.SUCCESS("密码重置成功");
    }

    /**
     * 修改邮箱
     *
     * @param email      邮箱
     * @param verifyCode 邮箱验证码
     */
    @Override
    @Transactional
    public R updateEmail(String email, String verifyCode) {
        UserVo userVo = LoginUserThreadLocalUtil.get();
        userUtilsService.getAndCheckEmailCode(email, verifyCode);
        UserBase userFromDB = userMapper.findByEmail(email);
        if (userFromDB != null) {
            return R.FAILED("邮箱已注册");
        }
        userFromDB = userMapper.findById(MyUtil.NumberUtil.asLong(userVo.getId()));
        userFromDB.setEmail(email);
        int i = userMapper.updateById(userFromDB);
        if (i == 0) {
            return R.FAILED("邮箱修改失败，请稍后重试");
        }
        userUtilsService.deleteOldToken(new UserVo(userFromDB), true);
        return R.SUCCESS("邮箱修改成功！");
    }

    /**
     * 修改手机号
     *
     * @param phone      手机号
     * @param verifyCode 手机验证码
     */
    @Override
    @Transactional
    public R updatePhone(String phone, String verifyCode) {
        UserVo userVo = LoginUserThreadLocalUtil.get();
        userUtilsService.getAndCheckEmailCode(phone, verifyCode);
        UserBase userFromDb = userMapper.findByPhone(phone);
        if (userFromDb != null) {
            return R.FAILED("手机号已注册");
        }
        userFromDb = userMapper.findById(MyUtil.NumberUtil.asLong(userVo.getId()));
        userFromDb.setPhone(phone);
        int i = userMapper.updateById(userFromDb);
        if (i == 0) {
            return R.FAILED("手机号修改失败");
        }
        userUtilsService.deleteOldToken(new UserVo(userFromDb), true);
        return R.SUCCESS("手机号修改成功！");
    }

    /**
     * 退出登录
     */
    @Override
    @Transactional
    public R logout() {
        UserVo userVo = LoginUserThreadLocalUtil.get();
        userUtilsService.deleteOldToken(userVo, false);
        return R.SUCCESS("退出登录成功！");
    }

    /**
     * 管理员 添加新用户
     */
    @Override
    public R addUserAdmin(UserDto userDto) {
        UserBase user = userDto.toEntity();

        String userName = user.getName();
        if (MyUtil.StringUtil.isEmpty(userName)) {
            throw new RuntimeException("用户名不能为空！");
        }
        if (userUtilsService.checkUserName(userName)) {
            throw new RuntimeException("此用户名已存在");
        }
        String email = user.getEmail();
        //检查邮箱格式是否正确。
        if (MyUtil.StringUtil.isEmpty(email)) {
            throw new RuntimeException("邮箱不能为空！");
        }
        if (!MyUtil.RegularUtil.isEmailAddresOk(email)) {
            throw new RuntimeException("邮箱格式不正确！");
        }
        //检查该邮箱是否已经注册。
        if (userUtilsService.checkEmail(email)) {
            throw new RuntimeException("邮箱已注册！");
        }
        Long powerId = user.getPowerId();
        if (powerId == null) {
            UserPower powerByName = userPowerMapper.findPowerByName(Constants.User.ROLE_USER_NAME);
            user.setPowerId(powerByName == null ? null : powerByName.getId());
        }
        user.setState(Constants.State.DEFAULT_STATE);
        user.setPassword(bcryptPasswordEncoder.encode(Constants.User.DEFAULT_PASSWORD));
        userMapper.insert(user);

        UserInfo userDetailInfo = getUserDetailInfo(user.getId());
        userInfoMapper.insert(userDetailInfo);
        return R.SUCCESS("新用户添加成功");
    }

    /**
     * 修改新用户
     *
     * @param userDto
     */
    @Override
    public R updateUser(UserDto userDto) {
        UserBase userBase = userDto.toEntity();
        Long id = userBase.getId();
        boolean own = permissionService.own("" + id);
        boolean root = permissionService.ROOT();
        boolean master = permissionService.MASTER();
        boolean admin = permissionService.ADMIN();
        if (!(root || own)) {
            throw new RuntimeException("您无权修改其他用户信息");
        }
        UserBase userBaseDB = userMapper.findAllInfoById(id);
        if (userBaseDB == null) {
            throw new RuntimeException("找不到此用户");
        }
        String name = userBase.getName();
        if (!MyUtil.StringUtil.isEmpty(name) && !name.equals(userBaseDB.getName())) {
            boolean hasName = userUtilsService.checkUserName(name);
            if (hasName) {
                throw new RuntimeException("用户名重复，请修改后重试");
            }
        }

        String email = userBase.getEmail();
        if (!MyUtil.StringUtil.isEmpty(email) && !email.equals(userBaseDB.getEmail())) {
            boolean hasEmail = userUtilsService.checkEmail(email);
            if (hasEmail) {
                throw new RuntimeException("邮箱重复，请修改后重试");
            }
        }

        String password = userDto.getPassword();
        UserInfo userInfo = userDto.getInfo();

        Integer powerNumber = userBase.getPower().getNumber();


        UserPower powerFromDb = userBaseDB.getPower();
        if (powerNumber != null && permissionService.checkIsRoot(powerFromDb.getNumber()) && !permissionService.checkIsRoot(powerNumber)) {
            throw new RuntimeException("root权限不可被更改");
        }
        if (!permissionService.own(userDto.getId()) && permissionService.checkIsRoot(powerNumber)) {
            throw new RuntimeException("站点仅允许一位root用户");
        }
        //管理员修改
        boolean flag = false;
        if (root || master || admin) {
            if (!MyUtil.StringUtil.isEmpty(password)) {
                userBase.setPassword(bcryptPasswordEncoder.encode(password));
                flag = true;
            }
            if (!MyUtil.StringUtil.isEmpty(powerNumber) && !powerFromDb.getNumber().equals(powerNumber)) {
                UserPower userPower = userPowerMapper.findByNumber(powerNumber);
                if (userPower != null && (permissionService.checkHighOwnPower(powerNumber) || root)) {
                    userBase.setPowerId(userPower.getId());
                    flag = true;
                } else {
                    throw new RuntimeException("您无权修改更高权限");
                }
            }
        }
        if (!root) {
            userBase.setPassword(null);
            userBase.setPowerId(null);
            userBase.setEmail(null);
            userBase.setRoleId(null);
            userBase.setState(null);
            userInfo.setMoney(null);
            userInfo.setAmount(null);
            userInfo.setReceiveState(null);
        }

        userInfo.setInvitationUser(null);
        userMapper.updateById(userBase);
        userInfoMapper.updateById(userInfo);
        if (flag) {
            userUtilsService.deleteOldToken(new UserVo(userBase), true);
        }

        return R.SUCCESS("《" + userBase.getName() + "》 用户信息修改完毕");
    }

    /**
     * 管理员 授权用户
     *
     * @param id
     */
    @Override
    @Transactional
    public R empower(String id) {
        Long idLong = MyUtil.NumberUtil.asLong(id);
        UserBase userDbById = userMapper.findAllInfoById(idLong);
        UserPower power = userDbById.getPower();
        Integer number = power.getNumber();
        if (!permissionService.checkIsUSER(number)) {
            throw new RuntimeException("您无法授权非游客用户");
        }
        UserPower powerByName = userPowerMapper.findPowerByName(Constants.User.ROLE_NORMAL_NAME);
        UserInfo userInfo = userInfoMapper.selectById(idLong);
        //设置邀请人信息
        Setting webInvitationRewards = settingMapper.findByKey(Constants.Settings.WEB_INVITATION_REWARDS);
        if (webInvitationRewards == null) {
            throw new RuntimeException("未设置邀请人奖励");
        }
        String money = userInfo.getMoney();
        Double aDouble = MyUtil.NumberUtil.asDouble(money);
        Double aDouble2 = MyUtil.NumberUtil.asDouble(webInvitationRewards.getValue());
        userInfo.setMoneyDouble(aDouble + aDouble2);

        userDbById.setPowerId(powerByName.getId());
        userMapper.updateById(userDbById);
        userInfoMapper.updateById(userInfo);
        userUtilsService.deleteOldToken(new UserVo(userDbById), true);
        return R.SUCCESS("用户已授权使用网站，并奖励金额：" + aDouble2);
    }

    /**
     * 管理员 封禁用户
     *
     * @param id
     */
    @Override
    public R banUser(String id) {
        UserBase userDbById = userMapper.findAllInfoById(MyUtil.NumberUtil.asLong(id));
        UserPower power = userDbById.getPower();
        Integer number = power.getNumber();
        UserVo userVo = LoginUserThreadLocalUtil.get();
        if (userVo.getId().equals(id)) {
            throw new RuntimeException("有啥想不开的？");
        }
        if (!permissionService.checkHighOwnPower(number)) {
            throw new RuntimeException("您无权封禁比自己权限更高的用户");
        }
        userDbById.setState(Constants.State.OTHER_STATE);
        userMapper.updateById(userDbById);
        //删除所有的缓存
        userUtilsService.deleteOldToken(new UserVo(userDbById), true);
        return R.SUCCESS("用户已禁止使用网站");
    }

    /**
     * 发送邮件
     *
     * @param sendEmailDto 邮件信息
     */
    @Override
    public R sendEmail(SendEmailDto sendEmailDto) {
        String toUserId = sendEmailDto.getToUserId();
        String msg = sendEmailDto.getMsg();
        String title = sendEmailDto.getTitle();
        String fromUserId = sendEmailDto.getFromUserId();

        List<String> toUserEmails = new ArrayList<>();
        if (MyUtil.StringUtil.isEmpty(toUserId)) {
            List<UserBase> userBaseList = userMapper.findAll(Constants.User.DEFAULT_AVATAR);
            toUserEmails = userBaseList.stream().map(UserBase::getEmail).toList();
        } else {
            UserBase userBase = userMapper.findById(MyUtil.NumberUtil.asLong(toUserId));
            if (userBase == null) {
                throw new RuntimeException("找不到发件人，请重试");
            }
            toUserEmails.add(userBase.getEmail());
        }

        if (MyUtil.StringUtil.isEmpty(fromUserId)) {
            for (String toUserEmail : toUserEmails) {
                userUtilsService.sendEmailAdmin(title, msg, toUserEmail);
            }
        } else {
            UserBase userBase = userMapper.findById(MyUtil.NumberUtil.asLong(fromUserId));
            if (userBase == null) {
                throw new RuntimeException("找不到收件人，请重试");
            }
            for (String toUserEmail : toUserEmails) {
                userUtilsService.sendEmailUser(userBase.getName(), title, msg, toUserEmail);
            }
        }

        return R.SUCCESS("邮件发送成功");
    }

    private final SettingMapper settingMapper;

    /**
     * 填写邀请码
     *
     * @param invitationCode 邀请码
     * @return 0
     */
    @Override
    @Transactional
    public R invitation(String invitationCode) {
        boolean normal = permissionService.NORMAL();
        if (!normal) {
            throw new RuntimeException("您暂未被授权，请联系管理员授权。");
        }
        UserVo userVo = LoginUserThreadLocalUtil.get();
        UserBase userMy = userMapper.findAllInfoById(MyUtil.NumberUtil.asLong(userVo.getId()));
        if (userMy == null) {
            throw new RuntimeException("找不到登录用户");
        }
        UserInfo info = userMy.getInfo();
        if (!MyUtil.StringUtil.isEmpty(info.getInvitationUser())) {
            throw new RuntimeException("邀请码不能重复填写");
        }

        UserBase userInvitation = userMapper.findByIdInvitationCode(invitationCode);
        if (userInvitation == null) {
            throw new RuntimeException("找不到邀请用户");
        }

        if (userMy.getId().equals(userInvitation.getId())) {
            throw new RuntimeException("不能自己邀请自己");
        }
        //设置被邀人信息
        info.setInvitationUser(userInvitation.getId());

        //设置邀请人信息
        Setting webInvitationRewards = settingMapper.findByKey(Constants.Settings.WEB_INVITATION_REWARDS);
        if (webInvitationRewards == null) {
            throw new RuntimeException("未设置邀请人奖励");
        }
        UserInfo userInvitationInfo = userInvitation.getInfo();
        String money = userInvitationInfo.getMoney();
        Double userInvitationMoneyDouble = MyUtil.NumberUtil.asDouble(money);
        Double webInvitationRewardsMoneyDouble = MyUtil.NumberUtil.asDouble(webInvitationRewards.getValue());

        userInvitationInfo.setMoneyDouble(userInvitationMoneyDouble + webInvitationRewardsMoneyDouble);
        userInfoMapper.updateById(userInvitationInfo);

        //设置邀请人奖励
        String myMoney = info.getMoney();
        Double myMoneyDouble = MyUtil.NumberUtil.asDouble(myMoney);
        Double myMoneyResultDouble = myMoneyDouble + webInvitationRewardsMoneyDouble;
        info.setMoneyDouble(myMoneyResultDouble);
        log.info("用户名 {}，填写邀请码后的金额：{}",userVo.getName(),myMoneyResultDouble);
        userInfoMapper.updateById(info);
        return R.SUCCESS("邀请码绑定成功,您获得奖励：" + webInvitationRewardsMoneyDouble).setData(userInvitation.getId().toString());
    }

    /**
     * 领取新人奖励
     *
     * @param addressId 地图ID
     */
    @Override
    public R receiveGift(String addressId) {
        UserVo userVo = LoginUserThreadLocalUtil.get();
        if (userVo == null) {
            throw new RuntimeException("请先登录");
        }
        if (MyUtil.StringUtil.isEmpty(addressId)) {
            throw new RuntimeException("请选择发货地图");
        }
        boolean normal = permissionService.NORMAL();
        if (!normal) {
            throw new RuntimeException("你未被授权，请联系管理员授权");
        }
        String id = userVo.getId();
        UserInfo userInfoDb = userInfoMapper.selectById(MyUtil.NumberUtil.asLong(id));
        if (userInfoDb == null) {
            throw new RuntimeException("找不到用户详细信息");
        }
        String receiveState = userInfoDb.getReceiveState();
        if ((Constants.Carmine.USED_STATE + "").equals(receiveState)) {
            throw new RuntimeException("您已经领取过新人奖励了，无法重复领取");
        }
        //设置邀请人信息
        Setting webNewUserGift = settingMapper.findByKey(Constants.Settings.WEB_NEW_USER_GIFT);
        if (webNewUserGift == null) {
            throw new RuntimeException("未设置新人奖励，请联系管理员设置");
        }
        String webNewUserGiftValue = webNewUserGift.getValue();
        String[] giftChar = webNewUserGiftValue.split(",");
        Long addressIdLong = MyUtil.NumberUtil.asLong(addressId);
        orderFromService.sendNewGift(Arrays.asList(giftChar), addressIdLong, userInfoDb);
        userInfoDb.setReceiveState(Constants.Carmine.USED_STATE + "");
        userInfoMapper.updateById(userInfoDb);
        return R.SUCCESS("领取新人奖励成功");
    }

    /**
     * 获取余额排行榜
     *
     * @param size 获取数量
     */
    @Override
    public R amountRanking(int size) {
        List<UserBase> list = userMapper.amountRanking(size, Constants.State.DEFAULT_STATE);
        return R.SUCCESS().setData(UserVo.change(list));
    }


}
